/////////////////////////////////////////////////////////////////////////////////////
// Include Files
#include "RenderSystem.h"
#include "RenderNode.h"

//// managers
//#include "Managers\TextureManager.h"
//#include "Managers\ShaderManager.h"
//#include "Managers\MeshManager.h"

//// rendering
//#include "Main\Camera.h"
//#include "Render\RenderState.h"

//// HACK?
//#include "Main\Game.h"
//
//#include "Cg\CgGL.h"

// TODO: 4x anti-aliasing, 8x anisotropic filtering, set in options?

/////////////////////////////////////////////////////////////////////////////////////
// CRenderSystem Implementation
void IE::CRenderSystem::Initialize()
{
	//m_hWnd = _hWnd;

	//// create camera
	//m_pCamera = new CCamera();
	//m_pCamera->Translate(0.0f, 0.0f, -30.0f);
	//m_pCamera->RotateViewAroundOrigin(0.3f, 0.7f);

	//// set the OpenGL viewport to the correct size
	//ReSizeGLScene(800, 600);

	// start the thread, the frame rate will be limited by vsync
	StartThread(0);
}

void IE::CRenderSystem::Shutdown()
{
	// stop the thread
	StopThread();

	//delete m_pCamera;
	//m_pCamera = CE_NULL;
}

//void CRenderer::OnMeshLoad( CMeshEventArg &_rArg )
//{
//	m_pMeshManager->CreateMesh(_rArg);
//}
//
//void CRenderer::OnShaderLoad( CShaderLoadEventArg &_rArg )
//{
//	m_pShaderManager->CreateShader(_rArg);
//}
//
//void CRenderer::OnTextureLoad( CTextureEventArg &_rArg )
//{
//	m_pTextureManager->CreateTexture(_rArg);
//}
//
//void CRenderer::OnRenderStateAdd( CRenderStateEventArg &_rArg )
//{
//	CRenderState *pState = _rArg.GetRenderState();
//	pState->AddRef();
//
//	for( uint_t i = 0; i < m_lstRenderStates.GetSize(); ++i )
//	{
//		if( m_lstRenderStates[i] == CE_NULL )
//		{
//			m_lstRenderStates[i] = pState;
//			return;
//		}
//	}
//	m_lstRenderStates.Append(pState);
//}
//
//void CRenderer::OnRenderStateRemove( CRenderStateEventArg &_rArg )
//{
//	CRenderState *pState = _rArg.GetRenderState();
//	pState->Release();
//
//	for( uint_t i = 0; i < m_lstRenderStates.GetSize(); ++i )
//	{
//		if( m_lstRenderStates[i] == pState )
//		{
//			m_lstRenderStates[i] = CE_NULL;
//			return;
//		}
//	}
//}
//
//void CRenderer::OnRenderStateUpdate( CRenderStateEventArg &_rArg )
//{
//	(void)_rArg;
//	// TODO
//}
//
//void CRenderer::OnMeshUpdate( CMeshEventArg &_rArg )
//{
//	m_pMeshManager->UpdateMesh(_rArg);
//}

void IE::CRenderSystem::ThreadBegin()
{
	//// get the application handle
	//HINSTANCE hApplication = GetModuleHandle(NULL);

	///////////////////////////////////////////////////////////////////////////////////
	//// initialize OpenGL 1.2 in a dummy window in order to load extensions

	//// dummy window class
	//WNDCLASSEX wcDummy = {
	//	sizeof(WNDCLASSEX),                 // cbSize
	//	CS_HREDRAW | CS_VREDRAW | CS_OWNDC, // style
	//	DefWindowProc,                      // lpfnWndProc
	//	0,                                  // cbClsExtra
	//	0,                                  // cbWndExtra
	//	hApplication,                       // hInstance
	//	NULL,                               // hIcon
	//	NULL,                               // hCursor
	//	NULL,                               // hbrBackground
	//	NULL,                               // lpszMenuName
	//	L"Dummy Window",                    // lpszClassName
	//	NULL};                              // hIconSm

	//if( !RegisterClassEx(&wcDummy) ) { assert(0); }

	//// dummy window
	//HWND hDummyWnd = CreateWindowEx(
	//	WS_EX_APPWINDOW,     // dwExStyle
	//	L"Dummy Window",     // lpClassName
	//	L"Dummy Window",     // lpWindowName
	//	WS_OVERLAPPEDWINDOW, // dwStyle
	//	0,                   // x
	//	0,                   // y
	//	800,                 // nWidth
	//	600,                 // nHeight
	//	NULL,                // hWndParent
	//	NULL,                // hMenu
	//	hApplication,        // hInstance
	//	NULL);               // lpParam

	//assert(hDummyWnd);

	//// dummy device context
	//HDC hDummyDC = GetDC(hDummyWnd);
	//assert(hDummyDC);

	//// dummy pixel format
	//int_t iDummyPF;

	//PIXELFORMATDESCRIPTOR pfdDummy = {
	//	sizeof(PIXELFORMATDESCRIPTOR),                              // nSize
	//	1,                                                          // nVersion
	//	PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, // dwFlags
	//	PFD_TYPE_RGBA,                                              // iPixelType
	//	32,                                                         // cColorBits
	//	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
	//	16,                                                         // cDepthBits
	//	0,                                                          // cStencilBits
	//	0,                                                          // cAuxBuffers
	//	PFD_MAIN_PLANE,                                             // iLayerType
	//	0, 0, 0, 0 };

	//iDummyPF = ChoosePixelFormat(hDummyDC, &pfdDummy);
	//assert(iDummyPF);

	//if( !SetPixelFormat(hDummyDC, iDummyPF, &pfdDummy) ) { assert(0); }

	//// dummy OpenGL context
	//HGLRC hDummyOGLC = wglCreateContext(hDummyDC);
	//assert(hDummyOGLC);

	//if( !wglMakeCurrent(hDummyDC, hDummyOGLC) ) { assert(false); }

	///////////////////////////////////////////////////////////////////////////////////
	//// load extensions and initialize the desired OpenGL version

	//// load extensions
	//GLExtInit();

	//// final device context
	//m_hGLDevice = GetDC(m_hWnd);
	//assert(m_hGLDevice);

	//// final pixel format
	//int_t iPixelFormat;
	//uint_t numformats;

	//int_t pf_attr[] = {
	//	WGL_ACCELERATION,   WGL_FULL_ACCELERATION, 
	//	WGL_DRAW_TO_WINDOW, GL_TRUE, 
	//	WGL_SUPPORT_OPENGL, GL_TRUE, 
	//	WGL_DOUBLE_BUFFER,  GL_TRUE, 
	//	WGL_PIXEL_TYPE,     WGL_TYPE_RGBA, 
	//	WGL_COLOR_BITS,     32, 
	//	WGL_DEPTH_BITS,     24, 
	//	0};

	//wglChoosePixelFormat(m_hGLDevice, pf_attr, NULL, 1, &iPixelFormat, &numformats);
	//assert(numformats);

	//if( !SetPixelFormat(m_hGLDevice, iPixelFormat, &pfdDummy) ) { assert(0); }

	//// final OpenGL context
	//int_t ctx_attr[] = {
	//	WGL_CONTEXT_MAJOR_VERSION, 4, 
	//	WGL_CONTEXT_MINOR_VERSION, 1, 
	//	WGL_CONTEXT_PROFILE_MASK, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT, 
	//	0
	//};

	//m_hGLRender = wglCreateContextAttribs(m_hGLDevice, 0, ctx_attr);
	//assert(m_hGLRender);

	//if( !wglMakeCurrent( m_hGLDevice, m_hGLRender ) ) { assert(0); }

	///////////////////////////////////////////////////////////////////////////////////
	//// destroy dummy initialization objects

	//if( !wglDeleteContext(hDummyOGLC) ) { assert(0); }
	//if( !DestroyWindow(hDummyWnd) ) { assert(0); }
	//if( !UnregisterClass(L"Dummy Window", hApplication) ) { assert(0); }

	///////////////////////////////////////////////////////////////////////////////////
	//// non-OpenGL initialization

	//// listen for asset load events
	//AddEventListener(m_pMeshManager->MeshLoad, &CRenderer::OnMeshLoad);
	//AddEventListener(m_pMeshManager->MeshUpdate, &CRenderer::OnMeshUpdate);
	//AddEventListener(m_pShaderManager->ShaderLoad, &CRenderer::OnShaderLoad);
	//AddEventListener(m_pTextureManager->TextureLoad, &CRenderer::OnTextureLoad);

	//// listen for render state events from the game
	//AddEventListener(m_pGame->RenderStateAdd, &CRenderer::OnRenderStateAdd);
	//AddEventListener(m_pGame->RenderStateRemove, &CRenderer::OnRenderStateRemove);
}

void IE::CRenderSystem::ThreadEnd()
{
	//// stop listening for render state events
	//RemoveEventListener(m_pGame->RenderStateRemove, &CRenderer::OnRenderStateRemove);
	//RemoveEventListener(m_pGame->RenderStateAdd, &CRenderer::OnRenderStateAdd);

	//// stop listening for asset load events
	//RemoveEventListener(m_pTextureManager->TextureLoad, &CRenderer::OnTextureLoad);
	//RemoveEventListener(m_pShaderManager->ShaderLoad, &CRenderer::OnShaderLoad);
	//RemoveEventListener(m_pMeshManager->MeshUpdate, &CRenderer::OnMeshUpdate);
	//RemoveEventListener(m_pMeshManager->MeshLoad, &CRenderer::OnMeshLoad);

	//// take care of any left over events
	//// TODO: is this a good thing or should I do something different?
	//ProcessEvents();

	//// destroy the OpenGL context
	//if( !wglMakeCurrent( CE_NULL, CE_NULL ) )
	//{
	//	assert(false);
	//}

	//if( !wglDeleteContext(m_hGLRender) )
	//{
	//	assert(false);
	//}
	//m_hGLRender = CE_NULL;
}

void IE::CRenderSystem::ThreadTick( float_t _fTime )
{
	(void)_fTime;
//
//	// check for errors
//#ifdef _DEBUG
//	GLenum eError2 = glGetError();
//	assert( eError2 == GL_NO_ERROR );
//#endif // _DEBUG
//
//	ProcessEvents();
//
//	// check for errors
//#ifdef _DEBUG
//	GLenum eError3 = glGetError();
//	assert( eError3 == GL_NO_ERROR );
//#endif // _DEBUG
//
//	/////////////////////////////////////////////////////////////////////////////
//	// HACK: camera movement
//
//	// move the camera around the origin
//	float_t fPosX = 0.0f, fPosY = 0.0f, fPosZ = 0.0f;
//	if( GetAsyncKeyState(VK_RIGHT) & 0x8000 ) fPosX += 0.523598f * _fTime;
//	if( GetAsyncKeyState(VK_LEFT ) & 0x8000 ) fPosX -= 0.523598f * _fTime;
//	if( GetAsyncKeyState(VK_UP   ) & 0x8000 ) fPosY += 0.523598f * _fTime;
//	if( GetAsyncKeyState(VK_DOWN ) & 0x8000 ) fPosY -= 0.523598f * _fTime;
//	if( GetAsyncKeyState(VK_PRIOR) & 0x8000 ) fPosZ += 30.0f * _fTime;
//	if( GetAsyncKeyState(VK_NEXT ) & 0x8000 ) fPosZ -= 30.0f * _fTime;
//	m_pCamera->RotateViewAroundOrigin(-fPosX, fPosY); // TODO: RotateViewArountPoint (sphere)
//	m_pCamera->Translate(0.0f, 0.0f, -fPosZ);
//
//	// limit zoom
//	if( m_pCamera->m_matTransform.arr[14] < 30.0f )  m_pCamera->m_matTransform.arr[14] = 30.0f;
//	if( m_pCamera->m_matTransform.arr[14] > 400.0f ) m_pCamera->m_matTransform.arr[14] = 400.0f;
//
//	// END HACK: camera movement
//	/////////////////////////////////////////////////////////////////////////////
//
//	// clear buffers
//	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//
//	// draw all render states TODO: remove Render() from CRenderState, do it here
//	matrix_t matView = m_pCamera->GetTransform();
//	matrix_t matProj = m_pCamera->GetProjection();
//
//	for( uint_t i = 0; i< m_lstRenderStates.GetSize(); ++i )
//	{
//		if( m_lstRenderStates[i] )
//		{
//			m_lstRenderStates[i]->Render(matView, matProj);
//		}
//	}
//
//	// show the new frame
//	SwapBuffers(m_hGLDevice);
//
//#ifdef _DEBUG
//	// make sure there have not been any errors
//	GLenum eError = glGetError();
//	assert(eError == GL_NO_ERROR);
//#endif _DEBUG
}

//void CRenderer::ReSizeGLScene(uint_t width, uint_t height)
//{
//	m_pCamera->SetPerspective( 45.0f, (float_t)width / height, 0.1f, 500.0f );
//}
